/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin			*/
/*	Project:	GlbCloud			*/
/*	Author:		gong_libin			*/
/*	Date:		2012_02_10			*/
/*	File:		MrPool.cpp			*/
/********************************************************/

#include "MrPool.h"

static void* (*sg_pPoolCore)(void*);

CMrPool::CMrPool()
{
	m_usTotal = 0;
	m_usCursor = 0;
	m_pCMember = NULL;
	m_pStartRoutine = NULL;
	memset(&m_stAttr, '\0', sizeof(pthread_attr_t));
}

CMrPool::CMrPool(USHORT usTotal)
{
	m_usCursor = 0;
	m_usTotal = usTotal;
	m_pStartRoutine = NULL;
	m_pCMember = new CMrMember[usTotal];
	memset(&m_stAttr, '\0', sizeof(pthread_attr_t));
}

CMrPool::~CMrPool()
{
	MrPoolDestroy();
	delete []m_pCMember;
}

USHORT CMrPool::MrPoolGetTotal()
{
	return m_usTotal;
}

void CMrPool::MrPoolDestroy()
{
	USHORT usCount = 0;

	for (; usCount < m_usTotal; usCount ++) {
		(m_pCMember + usCount)->MrThreadDestroy();
	}

	return;
}

int CMrPool::MrPoolAttrInit()
{
	if (MR_SUCCESS != pthread_attr_init(&m_stAttr)) {
		MR_ERROR("%s\n", strerror(errno));
		return MR_FAILURE;
	}

	return MR_SUCCESS;
}

int CMrPool::MrPoolCreate()
{
	USHORT usCount = 0;

	for (; usCount < m_usTotal; usCount ++) {
		(m_pCMember + usCount)->MrThreadAttrSet((void*)&m_stAttr);
		(m_pCMember + usCount)->MrThreadSetStartRoutine(m_pStartRoutine);
		if (MR_FAILURE == (m_pCMember + usCount)->MrThreadCreate(m_pCMember + usCount)) {
			return MR_FAILURE;
		}
	}

	return MR_SUCCESS;
}

void CMrPool::MrPoolJoin()
{
	USHORT usCount = 0;

	for (; usCount < m_usTotal; usCount ++) {
		(m_pCMember + usCount)->MrThreadJoin(NULL);
	}

	return;
}

void CMrPool::MrPoolSetStartRoutine(void* (*pStartRoutine)(void*))
{
	m_pStartRoutine = pStartRoutine;

	return;
}

void CMrPool::MrPoolSetTotal(USHORT usTotal)
{
	m_usTotal = usTotal;
	m_pCMember = new CMrMember[usTotal];

	return;
}

void CMrPool::MrPoolDistribute(void* pPara)
{
	while (MR_SUCCESS != (m_pCMember + m_usCursor)->MrMemberAssign(pPara)) {
		if (++ m_usCursor == m_usTotal) {
			m_usCursor = 0;
		}
	}

	return;
}

void* MrPoolStartRoutine(void* pSelf)
{
	while (true) {
		((CMrMember*)pSelf)->MrMemberLock();
		while (MR_IDLE == ((CMrMember*)pSelf)->MrMemberGetStatus()) {
			((CMrMember*)pSelf)->MrMemberWait();
		}
		((CMrMember*)pSelf)->MrMemberUnlock();

		(*sg_pPoolCore)(((CMrMember*)pSelf)->MrMemberGetKey());

		((CMrMember*)pSelf)->MrMemberLock();
		((CMrMember*)pSelf)->MrMemberSetStatus(MR_IDLE);
		((CMrMember*)pSelf)->MrMemberSetKey(NULL);
		((CMrMember*)pSelf)->MrMemberUnlock();
	}

	pthread_exit(NULL);
}

void MrPoolSetPoolCore(void* (*pPoolCore)(void*))
{
	sg_pPoolCore = pPoolCore;

	return;
}
